package org.javahispano.javacup.tacticas_aceptadas.jcrosas.chuky.util.matriz;

import java.util.ArrayList;

/**
 * @author Joan Crosas
 *
 */
public class Matriz {
	private ArrayList<MatrizColumna> columnas;
	private ArrayList<MatrizColumna> columnasDescartadas; // usado internamente para analizar la matriz
	private ArrayList<MatrizColumna> columnasInvertidas; // usado internamente para analizar la matriz invertida
	
	public Matriz() {
		columnas = new ArrayList<MatrizColumna>();
		columnasDescartadas = new ArrayList<MatrizColumna>();
		columnasInvertidas = new ArrayList<MatrizColumna>();
	}
	
	public void addColumna( MatrizColumna columna ) {
		columnas.add( columna );
		
	}
	
	public MatrizColumna min() {
		// ordenar las columnas
		for( int i = 0; i < columnas.size(); i++ ) {
			columnas.get(i).ordenar();
		}
		
		MatrizColumna min = null;
		
		// calculamos el min para X
		double valorMin = 500;
		for( int i = 0; i < columnas.size(); i++ ) {
			MatrizColumna minColumna = min( i );
			if( min == null ) {
				min = minColumna;
				valorMin = minColumna.getValor();
			} else if( minColumna.getValor() < valorMin ) {
				min = minColumna;
				valorMin = min.getValor();
			}
		}
		
		
		// invertimos la matriz
		int sizeColumna = columnas.get(0).size();
		for( int i = 0; i < sizeColumna; i++ ) {
			MatrizColumna newColumna = new MatrizColumna();
			for( int j = 0; j < columnas.size(); j++ ) {
				MatrizItem item = columnas.get(j).getItem(i);
				MatrizItem newItem = new MatrizItem( item.getObjectY(), item.getObjectX(), item.getValor() );
				newColumna.addItem( newItem );
			}
			columnasInvertidas.add( newColumna );
		}
		
		// intercambiamos las referencias
		ArrayList<MatrizColumna> columnasTmp = columnas;
		columnas = columnasInvertidas;
		columnasInvertidas = columnasTmp;
		
		// calculamos el min para Y
		for( int i = 0; i < columnas.size(); i++ ) {
			MatrizColumna minColumna = min( i );
			if( minColumna.getValor() < valorMin ) {
				min = minColumna;
				valorMin = min.getValor();
			}
		}
		
		return min;
	}
	
	private MatrizColumna min( int indice ) {
		MatrizColumna columnaAnalizada = columnas.get( indice );
		//ArrayList<MatrizItem> minColumna = new ArrayList<MatrizItem>();
		MatrizColumna minColumna = new MatrizColumna();
		ArrayList<Object> objsParaAnalizar = new ArrayList<Object>();
		
		columnasDescartadas.clear();
		columnasDescartadas.add( columnaAnalizada );
		
		minColumna.addItem( columnaAnalizada.getItem(0) );
		for( int i = 1; i < columnaAnalizada.size(); i++ ) {
			objsParaAnalizar.add( columnaAnalizada.getItem(i).getObjectY() );
		}
		
		while( objsParaAnalizar.size() > 0 ) {
			minColumna.addItem( min( objsParaAnalizar.get(0) ) );
			objsParaAnalizar.remove(0);
		}
		
		return minColumna;
	}
	
	
	private MatrizItem min( Object objectY ) {
		MatrizItem min = null;
		int indiceColumna = -1;
		
		for( int i = 0; i < columnas.size(); i++ ) {
			MatrizColumna columna = columnas.get(i);
			if( columnasDescartadas.indexOf( columna ) < 0 ) {
				for( int j = 0; j < columna.size(); j++ ) {
					if( columna.getItem(j).getObjectY() == objectY ) {
						if( min == null ) {
							min = columna.getItem(j);
							indiceColumna = i;
						} else if( columna.getItem(j).getValor() < min.getValor() ) {
							min = columna.getItem(j);
							indiceColumna = i;
						}
					}
				}
			}
		}
		
		columnasDescartadas.add( columnas.get( indiceColumna ) );
		return min;
		
	}
	
}
